// function echo(arg: any):any {
//     return arg
// }
// const result: string = echo(123) // bug 返回的是any 所以还是成立
// // 理论上应该返回number 泛型是指在定义函数、接口或类的时候不先指定类型
// // 而是在使用的时候才指定类型
function echo<T>(arg: T): T {
    return arg
}
// const result: string = echo(true) //不能将类型“boolean”分配给类型“string”。
const result = echo(true)

function swap<T, U>(tuple: [T, U]):  [U, T] {
    return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])
result2[1]
// 约束泛型
function echoWithAr<T>(arg: T[]): T[] {
    console.log(arg.length)
    return arg
}
const arrs = echoWithAr([1, 2, 3])

interface IWithLength {
    length: number
}
function echoWithLength<T extends IWithLength>(arg: T): T {
    console.log(arg.length)
    return arg
}
const str = echoWithLength('str')
const obj = echoWithLength( { length: 10} )
const arr2 = echoWithLength([1, 2, 3])
// echoWithLength(134)


// 泛型在类和接口中的使用
class GetMin<T>{
    arr:T[]=[];
    add(ele:T){
        this.arr.push(ele);
    }
   min():T{
      var min=this.arr[0];
      this.arr.forEach(function (value) {
         if(value<min){
             min=value;
         }
      });
      return min;
   }
}
 var gm1= new  GetMin<number>();
  gm1.add(5);
  gm1.add(3);
  gm1.add(2);
  gm1.add(9);
console.log(gm1.min());

var gm2= new  GetMin<string>();
gm2.add("z");
gm2.add("b");
gm2.add("c");
gm2.add("z");
console.log(gm2.min());

interface KeyPair<T, U> {
    key: T
    value: U
}
let kp1: KeyPair<number, string> = { key: 1, value: 'string' }
let kp2: KeyPair<string, number> = { key: 'str', value: 2 }
let arr: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]